function getLocaleReplacedUrl(url, oldLocale, locale) {
  const { URL } = require('url');
  const u = new URL(url);

  if (u.pathname === '/') {
    u.pathname = `/${locale}/m`;
  } else {
    u.pathname = u.pathname.replace(oldLocale, locale);
  }
  return u.href;
}

function getLocaleLink(url, locale) {
  return {
    rel: 'alternate',
    href: url,
    hreflang: locale
  };
}

function getLocaleReplacedLink(url, oldLocale, locale) {
  return getLocaleLink(getLocaleReplacedUrl(url, oldLocale, locale), locale);
}

// 获取不同语言对应的链接
function getAlternateLocaleLinks(data) {
  if (process.client) return [];
  const { pageUrl, locale } = data;
  if (!pageUrl) return [];
  const locales = ['zh', 'km', 'en'];
  const links = locales.map(s => getLocaleReplacedLink(pageUrl, locale, s));

  // 没有对应语言情况下，默认英语
  links.push(
    getLocaleLink(getLocaleReplacedUrl(pageUrl, locale, 'en'), 'x-default')
  );

  return links;
}

// get link
function getLink(data) {
  const links = [];
  if (data.desktopUrl) {
    links.push({
      rel: 'alternate',
      media: 'only screen and (min-width: 641px)',
      href: data.desktopUrl
    });
  }

  if (data.canonicalPageUrl) {
    links.push({
      rel: 'canonical',
      href: data.canonicalPageUrl
    });
  }

  return [...links, ...getAlternateLocaleLinks(data)];
}

// get Meta
function getNormalMeta(data) {
  const metas = [];
  if (data.keyword) {
    metas.push({
      name: 'keywords',
      content: data.keyword
    });
  }
  if (data.description) {
    metas.push({
      name: 'description',
      content: data.description
    });
  }
  return metas;
}

// open graph protocol
function getOgMeta(data) {
  return [
    {
      property: 'og:site_name',
      content: data.siteName
    },
    {
      property: 'og:title',
      content: data.title
    },
    {
      property: 'og:locale',
      content: data.pageLocale
    },
    {
      property: 'og:url',
      content: data.pageUrl
    },
    {
      property: 'og:image',
      content: data.thumb
    },
    {
      property: 'og:description',
      content: data.description
    }
  ];
}

// facebook meta
function getFbMeta() {
  return [
    {
      property: 'fb:app_id',
      content: '1756001284709028'
    }
  ];
}

// twitter meta
function getTwitterMeta(data) {
  return [
    {
      property: 'twitter:card',
      content: 'summary_large_image'
    },
    {
      property: 'twitter:site	',
      content: '@TNAOT_Official'
    },
    {
      property: 'twitter:title',
      content: data.title
    },
    {
      property: 'twitter:image',
      content: data.thumb
    },
    {
      property: 'twitter:image:src',
      content: data.thumb
    },
    {
      property: 'twitter:description',
      content: data.description
    },
    {
      property: 'twitter:domain',
      content: 'www.tnaot.com'
    }
  ];
}

export function mergeHead(...heads) {
  function isAtom(some) {
    if (typeof some === 'number') return true;
    if (typeof some === 'string') return true;
    if (typeof some === 'boolean') return true;
    if (some == null) return true;
    return false;
  }

  function isPlainObject(some) {
    return Object.prototype.toString.call(some) === '[object Object]';
  }

  function shallowMergeObject(target, source, satisfier = () => true) {
    if (!isPlainObject(target) && !isPlainObject(source)) return {};
    if (!isPlainObject(target)) return source;
    if (!isPlainObject(source)) return target;
    return Object.keys(source).reduce((result, key) => {
      const value = source[key];
      if (satisfier(source, key, result)) return { ...result, [key]: value };
      return result;
    }, target);
  }

  function shallowMergeArray(target, source) {
    if (!Array.isArray(target) && !Array.isArray(source)) return [];
    if (!Array.isArray(target)) return source;
    if (!Array.isArray(source)) return target;
    return [...target, ...source];
  }

  function mergeAtomKey(target, source) {
    return shallowMergeObject(target, source, (s, k) => isAtom(s[k]));
  }

  function uniqArray(array) {
    let map = {};
    return array.filter(value => {
      const uniqKey = JSON.stringify(value);
      if (map[uniqKey]) return false;
      map[uniqKey] = value;
      return true;
    });
  }

  function mergeAndUniqArray(target, source) {
    return uniqArray(shallowMergeArray(target, source));
  }

  function batchMergeArrayByKeys(keys, target, source) {
    return keys.reduce(
      (result, key) => ({
        ...result,
        [key]: mergeAndUniqArray(target[key], source[key])
      }),
      {}
    );
  }

  function merge(result, ...hs) {
    if (hs.length === 0) return result;
    const head = hs.shift();
    const nextResult = {
      ...mergeAtomKey(result, head),
      ...batchMergeArrayByKeys(
        ['meta', 'link', 'style', 'script'],
        result,
        head
      )
    };
    return merge(nextResult, ...hs);
  }

  if (heads.length === 0) return {};
  if (heads.length === 1) return heads[0];
  return merge({}, ...heads);
}

export function getMetaGetter(...metaGetters) {
  return data => metaGetters.reduce((result, f) => [...result, ...f(data)], []);
}

export function getHead(data) {
  const metaGetters = [getNormalMeta, getOgMeta, getFbMeta, getTwitterMeta];
  const getMeta = getMetaGetter(...metaGetters);

  return {
    title: data.title,
    meta: getMeta(data),
    link: getLink(data)
  };
}
